import paramiko
import hashlib
import daemon
import redis
import json
import time
import os


class Transfer:
   
    def __init__(self,ssh_args):
        self.ssh = paramiko.SSHClient()
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        self.ssh.connect(*ssh_args)
        self.sftp = self.ssh.open_sftp()
        self.file_handle = open(r"/data/fengyy/logfile/coperni_TransforDaemon.py.log", 'w')
    def __enter__(self):
        return self  # 返回自身或其他对象

    def __exit__(self, exc_type, exc_value, traceback):
        if exc_type is not None:
            print(f"Exception occurred: {exc_type}, {exc_value}")
        else:
            self.close()
    
    def makedir(self,remote_path):
        dirname = os.path.dirname(remote_path)
        try:
            self.sftp.listdir(dirname)
        except IOError as e:
            self.sftp.mkdir(dirname)
        return
    
    def check_remote_dir_and_create(self, remote_dir):
        # 检查远程目录是否存在
        stdin, stdout, stderr = self.ssh.exec_command(f'ls -d {remote_dir}')
        if not stdout.channel.recv_exit_status():
            # 远程目录不存在，创建远程目录
            command = f'mkdir -p {remote_dir}'
            stdin, stdout, stderr = self.ssh.exec_command(command)
            exit_status = stdout.channel.recv_exit_status()
            if exit_status != 0:
                raise Exception(f'Failed to create remote directory: {stderr.read().decode()}')

    def compare(self,local_file,remote_file):
        local_hash = hashlib.md5(open(local_file, 'rb').read()).hexdigest()
        with self.sftp.file(remote_file, 'rb') as f:
            remote_hash = hashlib.md5(f.read()).hexdigest()
        return local_hash == remote_hash

    def put_with_progress(self,local_path,remote_path):
        
        name = os.path.basename(local_path)
        def print_progress(transferred, total):
            temp = [0,10,20,30,40,50,60,70,80,90,100]
            # progress = round(transferred / total * 10) * 10
            # if progress in temp:
                # temp.pop(temp.index(progress))
                # print(f"{name}: Progress {progress:.0f}%", end='\r',file=self.file_handle) # , end='\r'
                
        temp_path = f'{remote_path}.incomplete'
        try: 
            self.sftp.put(local_path,temp_path,confirm=False,callback=print_progress)
            self.sftp.rename(temp_path, remote_path)
            return remote_path
        except IOError as e:
            time.sleep(60)
            return self.put_with_progress(local_path,remote_path)
        
    def single(self,local_path,remote_dir):
        if not os.path.exists(local_path): return
        self.check_remote_dir_and_create(remote_dir)  #  self.makedir(remote_dir)  远程目录创建
        file_name = os.path.basename(local_path)
        remote_path = os.path.join(remote_dir,file_name)
        try:
            file_stat = self.sftp.stat(remote_path)
            file_size = os.path.getsize(local_path)
            if file_stat.st_size == file_size:return remote_path
            else: return self.put_with_progress(local_path,remote_path)
        except FileNotFoundError as e:
            return self.put_with_progress(local_path,remote_path)
          
    def close(self):
        self.sftp.close()
        self.ssh.close()


def main():
    with open('/data/fengyy/project/CopernicusSentinel2Level1C/main/config.json',"r") as file:
        params = json.load(file)
    ssh_args = params['ssh_args'] 
    remote_folder = params['remote_dir']
    rediscon = params["rediscon"]
    pool = redis.ConnectionPool(**rediscon)
    redisr = redis.Redis(connection_pool=pool)
    with Transfer(ssh_args) as transfer:
        while True:
            _,element = redisr.brpop('downloader_transfer',0)
            local_path = element.decode('utf-8')
            dir_name = os.path.dirname(local_path)
            yearmonth = os.path.basename(dir_name)
            remote_dir = os.path.join(remote_folder,yearmonth)
            # try:
            print(remote_dir,os.path.basename(local_path))
            result = transfer.single(local_path,remote_dir)
            redisr.lpush('transfer_sender', result)
                # if result: redisr.lpush('transfer_sender', result)
            # except:
            #     time.sleep(60*5)
            #     redisr.lpush('downloader_transfer', element)
    return


def run_daemon():
    with daemon.DaemonContext(
        stdout=open(r"/data/fengyy/logfile/coperni_TransforDaemon.py.log","w"),
        stderr=open(r"/data/fengyy/logfile/coperni_TransforDaemon.py.log","w")
        ):
        
        main()
    return


if __name__ == "__main__":
    # main()
    run_daemon()